package utils
{
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	
	import mx.logging.ILogger;
	import mx.logging.Log;
	import mx.logging.LogEvent;
	import mx.logging.LogEventLevel;
	
	/**
	 * 
	 * @author Fabián Aramendi
	 * 
	 * This Class helps to implement the scroll object ability for custom Objects
	 * 
	 * 
	 */
	public class Scroller
	{
		private var _thisStage:Stage;
		private var _target:MovieClip = new MovieClip;
		private var _mask:MovieClip = new MovieClip;
		private var _scrollBarComponent:MovieClip;
		
		private var _scrollDragger:MovieClip;
		private var _scrollBar:MovieClip;
		private var _draggerColor:uint=0x999999;
		private var _scrollerColor:uint=0xDDDDDD;

		private var _maskDefault:MovieClip;
		
		private var _visibleWidthMask:Number=0;
		private var _visibleHeightMask:Number=0;
		private var _visibleWidthScroll:Number=0;
		private var _visibleHeightScroll:Number=0;

		
		private var _scrollBarComponentDefault:MovieClip;
		private var _scrollDraggerDefault:MovieClip;
		private var _scrollBarDefault:MovieClip;
		private var _initialtargetPosition:Number;
		private var _customScroll:Boolean;
		private var _scrollHorizontal:Boolean;
		
		private static var logger:ILogger = Log.getLogger("Scroller");


		
		/**
		 * 
		 * @param newStage = StageReference
		 * @param newTarget = Object to Scroll
		 * @param newScrollBar = MovieClip to use as ScrollBar must have an child MovieClip named "scrollDragger" and other colled "scrollBar"
		 * 
		 */
		public function Scroller(newStage:Stage, newTarget:MovieClip, newScrollBar:MovieClip=null)
		{
			logger.log(LogEventLevel.INFO, "Scroller");

			thisStage=newStage
			target=newTarget;
			
			if (newScrollBar!=null){
				customScroll=true;
				scrollBarComponent=newScrollBar;
			} else {
				customScroll=false;
			}
		}
		
		private function setScrollBarShape():void
		{
			_scrollDraggerDefault=new MovieClip;
			_scrollDraggerDefault.graphics.beginFill(_draggerColor, 1);
			_scrollDraggerDefault.graphics.drawRect(0, 0, _visibleWidthScroll, _visibleHeightScroll/10);
			_scrollDraggerDefault.graphics.endFill();
			_scrollBarDefault=new MovieClip;
			_scrollBarDefault.graphics.beginFill(_scrollerColor, 1);
			_scrollBarDefault.graphics.drawRect(0, 0, _visibleWidthScroll, _visibleHeightScroll);
			_scrollBarDefault.graphics.endFill();
			
			scrollDragger=_scrollDraggerDefault;
			scrollBar=_scrollBarDefault;
			
			makeScrollBar();
			
		}
		
		private function makeScrollBar():void{
			_scrollBarComponentDefault = new MovieClip;
			_scrollBarComponentDefault.addChild(scrollBar);
			_scrollBarComponentDefault.addChild(scrollDragger);
			scrollBarComponent=_scrollBarComponentDefault;
		}
		
		public function updateSize():void {
			if (!_scrollHorizontal){
				if (target.height<=mask.height) {
					scrollBarComponent.visible=false;
				}else{
					scrollBarComponent.visible=true;
				}
			}else{
				if (target.width<=mask.width) {
					scrollBarComponent.visible=false;
				}else{
					scrollBarComponent.visible=true;
				}
			}
		}
		
		public function get mask():MovieClip
		{
			return _mask;
		}

		public function set mask(value:MovieClip):void
		{
			_mask = value;
		}

		public function get scrollBarComponent():MovieClip
		{
			return _scrollBarComponent;
		}

		public function set scrollBarComponent(value:MovieClip):void
		{
			_scrollBarComponent = value;
			if (customScroll) {
				scrollDragger=_scrollBarComponent.getChildByName("scrollDragger") as MovieClip;
				scrollBar=_scrollBarComponent.getChildByName("scrollBar") as MovieClip;
			} else {
				if (!_scrollHorizontal){
					_scrollBarComponent.x=target.x+target.width;
					_scrollBarComponent.y=target.y;
				}else{
					//TODO ADJUST TO HORIZONTAL
					_scrollBarComponent.x=target.x+target.width;
					_scrollBarComponent.y=target.y;
				}
				target.parent.addChildAt(_scrollBarComponent, target.parent.numChildren);
			}
		}
		
		public function setShapeMask():void {
			if (_maskDefault==null) {
				_maskDefault = new MovieClip;
			}
			_maskDefault.graphics.beginFill(0x000000, 1);
			_maskDefault.graphics.drawRect(target.x, target.y, _visibleWidthMask, _visibleHeightMask);
			_maskDefault.graphics.endFill();
			target.parent.addChild(_maskDefault);
			mask=_maskDefault;
			updateSize();
			initMask();
		}
		
		private function initMask():void {
			target.mask=mask;
		}
		
		private function initScroller():void {
			// TODO Auto Generated method stub
		}
		
		public function init(_wS:Number, _hS:Number, _wM:Number, _hM:Number):void {
			setScrollBarSize(_wS, _hS);
			setMaskSize(_wM,_hM);
		}
		
		public function setScrollBarSize(_w:Number, _h:Number):void {
			_visibleWidthScroll=_w;
			_visibleHeightScroll=_h;
			setScrollBarShape();
		}
		
		public function setMaskSize(_w:Number, _h:Number):void {
			_visibleWidthMask=_w;
			_visibleHeightMask=_h;
			setShapeMask()
		}

		public function get target():MovieClip
		{
			return _target;
		}

		public function set target(value:MovieClip):void
		{
			_target = value;
			if(!_scrollHorizontal) {
				_initialtargetPosition=target.y;
			}else{
				_initialtargetPosition=target.x;
			}
		}

		public function get maskDefault():MovieClip
		{
			return _maskDefault;
		}

		public function set maskDefault(value:MovieClip):void
		{
			_maskDefault = value;
		}

		public function get visibleWidth():Number
		{
			return _visibleWidthMask;
		}

		public function set visibleWidth(value:Number):void
		{
			_visibleWidthMask = value;
		}

		public function get visibleHeight():Number
		{
			return _visibleHeightMask;
		}

		public function set visibleHeight(value:Number):void
		{
			_visibleHeightMask = value;
		}

		public function get scrollDragger():MovieClip
		{
			return _scrollDragger;
		}

		public function set scrollDragger(value:MovieClip):void
		{
			_scrollDragger = value;
			_scrollDragger.buttonMode=true;
			_scrollDragger.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
			_scrollDragger.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
		}
		
		private function startDragging(event:MouseEvent):void
		{
			_scrollDragger.addEventListener(Event.ENTER_FRAME, dragBar);
			_scrollDragger.removeEventListener(MouseEvent.MOUSE_DOWN, startDragging);
			_scrollDragger.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
			_thisStage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
		}
		
		private function dragBar(event:Event):void
		{
			if (!_scrollHorizontal) {
				_scrollDragger.startDrag(false, new Rectangle(_scrollBar.x, _scrollBar.y, _scrollBar.width-_scrollDragger.width, _scrollBar.height-_scrollDragger.height));
				setTextPostion(calculateBarPositionPercent());
			}else{
				_scrollDragger.startDrag(false, new Rectangle(_scrollBar.x, _scrollBar.y, _scrollBar.width-_scrollDragger.width, _scrollBar.height-_scrollDragger.height));
				setTextPostion(calculateBarPositionPercent());
			}
		}
		
		private function setTextPostion(value:Number):void
		{
			if (!_scrollHorizontal) {
				target.y=initialtargetPosition-(((target.height-mask.height)/100)*value);
			}else{
				target.x=initialtargetPosition-(((target.width-mask.width)/100)*value);
			}
		}
		
		public function forceScroll(percent:Number):void {
			if (!_scrollHorizontal) {
				if (target.height>mask.height) {
					updateSize();
					if (percent>100){
						percent=100;
					} else if (percent<0) {
						percent=0;
					}
					setTextPostion(percent);
					setDraggerPosition(percent);
				}
			}else{
				if (target.width>mask.width) {
					updateSize();
					if (percent>100){
						percent=100;
					} else if (percent<0) {
						percent=0;
					}
					setTextPostion(percent);
					setDraggerPosition(percent);
				}
			}
		}
		
		private function setDraggerPosition(value:Number):void
		{
			if (!_scrollHorizontal) {
				var resultPosition:Number=(((_scrollBar.y+_scrollBar.height-_scrollDragger.height)-(_scrollBar.y))/100)*value;
				_scrollDragger.y=_scrollBar.y+resultPosition;
			}else{
				//TODO ADJUST TO HORIZONTAL
				var resultPositionHorizontal:Number=(((_scrollBar.y+_scrollBar.height-_scrollDragger.height)-(_scrollBar.y))/100)*value;
				_scrollDragger.y=_scrollBar.y+resultPositionHorizontal;
			}
		}
		
		private function calculateBarPositionPercent():Number
		{
			var result:Number;
			if (!_scrollHorizontal) {
				var totalSize:Number=_scrollBar.y+_scrollBar.height-_scrollDragger.height;
				var actualPosition:Number=(_scrollBar.y+_scrollBar.height-_scrollDragger.height)-(_scrollBar.y-_scrollDragger.y);
				result= Math.ceil(((actualPosition*100)/totalSize)-100);
			}else{
				var totalSizeHorizontal:Number=_scrollBar.x+_scrollBar.width-_scrollDragger.width;
				var actualPositionHorizontal:Number=(_scrollBar.x+_scrollBar.width-_scrollDragger.width)-(_scrollBar.x-_scrollDragger.x);
				result= Math.ceil(((actualPositionHorizontal*100)/totalSizeHorizontal)-100);
			}
			return result;		
		}
		
		private function stopDragging(event:MouseEvent):void
		{
			_scrollDragger.stopDrag();
			_scrollDragger.removeEventListener(Event.ENTER_FRAME, dragBar);
			_scrollDragger.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
			_scrollDragger.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
			_thisStage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
		}
		
		public function get scrollBar():MovieClip
		{
			return _scrollBar;
		}

		public function set scrollBar(value:MovieClip):void
		{
			_scrollBar = value;
		}

		public function get scrollBarComponentDefault():MovieClip
		{
			return _scrollBarComponentDefault;
		}

		public function set scrollBarComponentDefault(value:MovieClip):void
		{
			_scrollBarComponentDefault = value;
		}

		public function get thisStage():Stage
		{
			return _thisStage;
		}

		public function set thisStage(value:Stage):void
		{
			_thisStage = value;
		}

		public function get initialtargetPosition():Number
		{
			return _initialtargetPosition;
		}

		public function set initialtargetPosition(value:Number):void
		{
			_initialtargetPosition = value;
		}

		public function get customScroll():Boolean
		{
			return _customScroll;
		}

		public function set customScroll(value:Boolean):void
		{
			_customScroll = value;
		}

		public function get draggerColor():uint
		{
			return _draggerColor;
		}

		public function set draggerColor(value:uint):void
		{
			_draggerColor = value;
			setScrollBarShape();
		}

		public function get scrollerColor():uint
		{
			return _scrollerColor;
		}

		public function set scrollerColor(value:uint):void
		{
			_scrollerColor = value;
			setScrollBarShape();
		}

		public function get scrollHorizontal():Boolean
		{
			return _scrollHorizontal;
		}

		public function set scrollHorizontal(value:Boolean):void
		{
			_scrollHorizontal = value;
		}


	}
}